package com.lagou.filter;

import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ConcurrentHashMap;

@Activate(group = CommonConstants.CONSUMER)
public class TPMonitorFilter implements Filter {

    private static Logger LOGGER = LoggerFactory.getLogger(TPMonitorFilter.class);

    private static ConcurrentHashMap<String, Monitor> map = new ConcurrentHashMap<String, Monitor>();

    private static Long requestLastTime = 0L;

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        //开始时间
        Long startTime = System.currentTimeMillis();
        Result invoke = invoker.invoke(invocation);
        //耗时
        Long requestUsedTime = System.currentTimeMillis() - startTime;

        //缓存方法调用情况
        String methodName = invocation.getMethodName();
        Monitor monitor = map.get(methodName);
        if(monitor==null){
            monitor= Monitor.getInstance();
        }
        map.put(methodName,monitor);
        monitor.saveRequestInfo(methodName, requestUsedTime);

        //5秒钟打印一次
        if (requestLastTime == 0 || (System.currentTimeMillis() - requestLastTime) >= 5000) {
            requestLastTime = System.currentTimeMillis();

            //遍历出每一个方法的TP90、TP99的耗时情况
            for (Monitor monitorValue : map.values()) {
                Long tp90 = monitorValue.getTP(0.9F);
                Long tp99 = monitorValue.getTP(0.99F);

                LOGGER.info("------IP: " + RpcContext.getContext().getRemoteHost()
                    + ", Service: " + invoker.getInterface().getName()
                    + ", Method: " + monitorValue.getMethodName()
                    + ", requestCount: " + monitorValue.getRequestCount()
                    + ", TP90: " + tp90 + "ms"
                    + ", TP99: " + tp99 + "ms"
                );
            }
        }
        return invoke;
    }
}
